//
//  NSString+JwRegex.m
//  JwPack
//
//  Created by 陈警卫 on 2024-07-17.
//

#import "NSString+JwRegex.h"

@implementation NSString (JwRegex)

/// 判断是否包含中文符号
- (BOOL)jw_includeChineseSymbol {
    NSArray *chinesePunctuation = @[@"。", @"？", @"！", @"，", @"、", @"；", @"：", @"「", @"」", @"『", @"』", @"‘", @"’", @"“",
                                    @"”", @"（", @"）", @"〔", @"〕", @"【", @"】", @"—", @"…", @"–", @"．", @"《", @"》", @"〈", @"〉",];
    for (NSString *symbol in chinesePunctuation) {
        if ([self rangeOfString:symbol].location != NSNotFound) {
            return YES;
        }
    }
    return NO;
}

/// 判断是否包含汉字
- (BOOL)jw_includeChinese {
    for(NSInteger i = 0; i < [self length]; i++){
        NSInteger cvlaue = [self characterAtIndex:i];
        if (cvlaue > 0x4E00 && cvlaue < 0x9FFF){
            return YES;
        }
    }
    return NO;
}

/// 验证数字
- (BOOL)jw_isDecimal {
    if ([self length] <= 0) {
        return NO;
    }
    NSString *value = [self stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];
    value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if (value.length > 0) {
        return NO;
    }
    return YES;
}

/// 验证数字
- (BOOL)jw_isNumber {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^[0-9]*$"];
    return [predicate evaluateWithObject:self];
}

/// 验证数字和小数点
- (BOOL)jw_isNumberAndPoint {
    if ([self length] <= 0) {
        return NO;
    }
    NSCharacterSet *numberAndPoint = [NSCharacterSet characterSetWithCharactersInString:@"0123456789."];
    NSString *value = [self stringByTrimmingCharactersInSet:numberAndPoint];
    value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if (value.length > 0) {
        return NO;
    }
    return YES;
}

/// 验证邮箱
- (BOOL)jw_isEmail {
    if ([self length] <= 0) {
        return NO;
    }
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"];
    return [predicate evaluateWithObject:self];
}

/// 验证手机号码
- (BOOL)jw_isPhone {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^1[0-9]{10}$"];
    return [predicate evaluateWithObject:self];
}

/// 验证邮政编码
- (BOOL)jw_isPostal {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^[1-9]\\d{5}｜000000$"];
    return [predicate evaluateWithObject:self];
}

/// 验证全中文
- (BOOL)jw_isAllChinese {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"(^[\\u4E00-\\u9FA5]+$)"];
    return [predicate evaluateWithObject:self];
}

/// 简单验证身份证
- (BOOL)jw_isIDCard {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^(\\d{14}|\\d{17})(\\d|[xX])$"];
    return [predicate evaluateWithObject:self];
}

/// 密码验证 既有数字又有字母
- (BOOL)jw_isPassword {
    if ([self length] <= 0) {
        return NO;
    }
    NSRegularExpression *numRegex = [NSRegularExpression regularExpressionWithPattern:@"[0-9]" options:0 error:nil];
    NSRegularExpression *letRegex = [NSRegularExpression regularExpressionWithPattern:@"[A-Za-z]" options:0 error:nil];
    NSUInteger numCount = [numRegex numberOfMatchesInString:self options:0 range:NSMakeRange(0, [self length])];
    NSUInteger letCount = [letRegex numberOfMatchesInString:self options:0 range:NSMakeRange(0, [self length])];
    return (numCount + letCount == [self length]) && (numCount > 0 && letCount > 0);
}

/// 密码验证 既有数字又有字母 位数
- (BOOL)jw_isPasswordWithMin:(NSUInteger)min max:(NSUInteger)max {
    NSString *regex = [NSString stringWithFormat:@"^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{%lu,%lu}$", (unsigned long)min, (unsigned long)max];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [predicate evaluateWithObject:self];
}

/// 验证url字符串
- (BOOL)jw_isUrlString {
    NSString *regex = @"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\-.]+(?::(\\d+))?(?:(?:/[a-zA-Z0-9\\-._?,'+\\&%$=~*!():@\\\\]*)+)?)|(www.[a-zA-Z0-9\\.\\-]+\\.(?:[a-zA-Z]{2,4})(?::\\d+)?(?:/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [predicate evaluateWithObject:self];
}

/// 验证身份证
- (BOOL)jw_isIDCardStrong {
    if (![self jw_isIDCard]) {
        return NO;
    }
    NSString *value = self;
    // 省份代码
    NSArray *areasArray =@[@"11",@"12", @"13",@"14", @"15",@"21", @"22",@"23", @"31",@"32", @"33",@"34", @"35",@"36", @"37",@"41",@"42",@"43", @"44",@"45", @"46",@"50", @"51",@"52", @"53",@"54", @"61",@"62", @"63",@"64", @"65",@"71", @"81",@"82", @"91"];
    NSString *area = [value substringToIndex:2];
    BOOL areaFlag = NO;
    for (NSString *areaCode in areasArray) {
        if ([areaCode isEqualToString:area]) {
            areaFlag = YES;
            break;
        }
    }
    if (!areaFlag) {
        return NO;
    }
    // 加权因子
    NSArray *idCardWiArr = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
    // 校验码
    NSArray *idCardYArr = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
    // 15位转18位
    if (value.length == 15) {
        NSMutableString *mstr = [NSMutableString stringWithString:value];
        [mstr insertString:@"19" atIndex:6];
        NSInteger idCardWiSum = 0;
        for (NSInteger i = 0; i < 17; i++) {
            NSInteger subStrIndex = [[mstr substringWithRange:NSMakeRange(i, 1)] integerValue];
            NSInteger idCardWiIndex = [[idCardWiArr objectAtIndex:i] integerValue];
            idCardWiSum += subStrIndex * idCardWiIndex;
        }
        NSInteger idCardMod = idCardWiSum%11;
        [mstr insertString:idCardYArr[idCardMod] atIndex:[mstr length]];
        value = mstr;
    }
    // 判断生日是否合法
    NSRange range = NSMakeRange(6, 8);
    NSString *datestr = [value substringWithRange:range];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyyMMdd"];
    if ([formatter dateFromString:datestr]==nil){
        return NO;
    }
    // 用来保存前17位各自乖以加权因子后的总和
    NSInteger idCardWiSum = 0;
    for (NSInteger i = 0; i < 17; i++) {
        NSInteger subStrIndex = [[value substringWithRange:NSMakeRange(i, 1)] integerValue];
        NSInteger idCardWiIndex = [[idCardWiArr objectAtIndex:i] integerValue];
        idCardWiSum += subStrIndex * idCardWiIndex;
    }
    // 计算出校验码所在数组的位置
    NSInteger idCardMod = idCardWiSum%11;
    // 得到最后一位身份证号码
    NSString *idCardLast = [value substringWithRange:NSMakeRange(17, 1)];
    // 如果等于2，则说明校验码是10，身份证号码最后一位应该是X
    if (idCardMod == 2) {
        if (![idCardLast isEqualToString:@"X"] || ![idCardLast isEqualToString:@"x"]) {
            return NO;
        }
    } else {
        // 用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
        if (![idCardLast isEqualToString:[idCardYArr objectAtIndex:idCardMod]]) {
            return NO;
        }
    }
    return YES;
}

/// 验证银行卡
- (BOOL)jw_isBankCard {
    NSString *str = self;
    if (str == nil || str.length <= 0) {
        return NO;
    }
    NSString * lastNum = [[str substringFromIndex:(str.length-1)] copy]; // 取出最后一位
    NSString * forwardNum = [[str substringToIndex:(str.length -1)] copy]; // 前15或18位
    
    NSMutableArray * forwardArr = [[NSMutableArray alloc] initWithCapacity:0];
    for (NSInteger i = 0; i < forwardNum.length; i++) {
        NSString *subStr = [forwardNum substringWithRange:NSMakeRange(i, 1)];
        [forwardArr addObject:subStr];
    }
    
    NSMutableArray *forwardDescArr = [[NSMutableArray alloc] initWithCapacity:0];
    for (NSInteger i = (forwardArr.count - 1); i > -1; i--) { // 前15位或者前18位倒序存进数组
        [forwardDescArr addObject:forwardArr[i]];
    }
    
    NSMutableArray * arrOddNum = [[NSMutableArray alloc] initWithCapacity:0]; // 奇数位*2的积 < 9
    NSMutableArray * arrOddNum2 = [[NSMutableArray alloc] initWithCapacity:0]; // 奇数位*2的积 > 9
    NSMutableArray * arrEvenNum = [[NSMutableArray alloc] initWithCapacity:0]; // 偶数位数组
    
    for (NSInteger i = 0; i < forwardDescArr.count; i++) {
        NSInteger num = [forwardDescArr[i] intValue];
        if (i%2) { // 偶数位
            [arrEvenNum addObject:[NSNumber numberWithInteger:num]];
        } else { // 奇数位
            if (num * 2 < 9) {
                [arrOddNum addObject:[NSNumber numberWithInteger:num * 2]];
            } else {
                NSInteger decadeNum = (num * 2) / 10;
                NSInteger unitNum = (num * 2) % 10;
                [arrOddNum2 addObject:[NSNumber numberWithInteger:unitNum]];
                [arrOddNum2 addObject:[NSNumber numberWithInteger:decadeNum]];
            }
        }
    }
    
    __block  NSInteger sumOddNumTotal = 0;
    [arrOddNum enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
        sumOddNumTotal += [obj integerValue];
    }];
    
    __block NSInteger sumOddNum2Total = 0;
    [arrOddNum2 enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
        sumOddNum2Total += [obj integerValue];
    }];
    
    __block NSInteger sumEvenNumTotal = 0 ;
    [arrEvenNum enumerateObjectsUsingBlock:^(NSNumber * obj, NSUInteger idx, BOOL *stop) {
        sumEvenNumTotal += [obj integerValue];
    }];
    
    NSInteger lastNumber = [lastNum integerValue];
    NSInteger luhmTotal = lastNumber + sumEvenNumTotal + sumOddNum2Total + sumOddNumTotal;
    return (luhmTotal%10 == 0) ? YES : NO;
}

@end
